package com.wjk.kylin.mall.auth.security.core.userdetails.user;

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSONObject;
import com.wjk.kylin.mall.auth.exception.UserNotFoundRoleException;
import com.wjk.kylin.mall.auth.feign.AdminFeignService;
import com.wjk.kylin.mall.common.core.bo.admin.UserNameBO;
import com.wjk.kylin.mall.common.core.constant.Constants;
import com.wjk.kylin.mall.common.core.dto.admin.UserIdInDTO;
import com.wjk.kylin.mall.common.core.dto.admin.UserNameInDTO;
import com.wjk.kylin.mall.common.core.dto.base.DataOutDTO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AccountExpiredException;
import org.springframework.security.authentication.DisabledException;
import org.springframework.security.authentication.LockedException;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

/**
 * 系统用户体系业务类
 *
 * @author <a href="mailto:xianrui0365@163.com">xianrui</a>
 */
@Slf4j
@Service
public class AdminUserDetailsServiceImpl implements UserDetailsService {

    @Autowired
    private AdminFeignService adminFeignService;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        AdminUserDetails userDetails = new AdminUserDetails(getUserNameBO(username));

        //TODO 测试
        List<SimpleGrantedAuthority> authorities = new ArrayList<>();
        List<Long> roleList = getRoleIdByUserId(userDetails.getUserId());

        roleList.forEach(e->{
            authorities.add(new SimpleGrantedAuthority(String.valueOf(e)));
        });
        userDetails.setAuthorities(authorities);

        if (userDetails == null) {
            throw new UsernameNotFoundException("登录用户：[" + username + "]不存在");
        } else if (!userDetails.isEnabled()) {
            throw new DisabledException("对不起，您的账号：[" + username + "]已禁用");
        } else if (!userDetails.isAccountNonLocked()) {
            throw new LockedException("对不起，您的账号：[" + username + "]已锁定");
        } else if (!userDetails.isAccountNonExpired()) {
            throw new AccountExpiredException("对不起，您的账号：[" + username + "]已过期");
        }

        log.info("登录用户：[{}]，用户信息：[{}]", username, JSONObject.toJSONString(userDetails));
        return userDetails;
    }

    /**
     * 查询管理后台用户
     *
     * @param username
     * @returnd
     */
    private UserNameBO getUserNameBO(String username) {
        UserNameInDTO inDTO = new UserNameInDTO();
        inDTO.setUsername(username);
        DataOutDTO<UserNameBO> outDTO = adminFeignService.loadUserByUsername(inDTO);
        if (outDTO == null || outDTO.getCode() != Constants.SUCCESS || outDTO.getData() == null) {
            throw new UsernameNotFoundException("登录用户：[" + username + "]不存在");
        }
        return outDTO.getData();
    }

    /**
     * 查询管理后台用户权限
     *
     * @param userId
     * @return
     */
    private List<String> getMenuPermsByUser(Long userId) {
        UserIdInDTO inDTO = new UserIdInDTO();
        inDTO.setUserId(userId);
        DataOutDTO<List<String>> outDTO = adminFeignService.getMenuPermsByUser(inDTO);
        if (outDTO == null || outDTO.getCode() != Constants.SUCCESS || CollectionUtil.isEmpty(outDTO.getData())) {
            throw new UserNotFoundRoleException("登录用户id：[" + userId + "],无权限");
        }
        return outDTO.getData();
    }

    /**
     * 查询管理后台用户权限
     *
     * @param userId
     * @return
     */
    private List<Long> getRoleIdByUserId(Long userId) {
        UserIdInDTO inDTO = new UserIdInDTO();
        inDTO.setUserId(userId);
        DataOutDTO<List<Long>> outDTO = adminFeignService.getRoleIdByUserId(inDTO);
        if (outDTO == null || outDTO.getCode() != Constants.SUCCESS || CollectionUtil.isEmpty(outDTO.getData())) {
            throw new UserNotFoundRoleException("登录用户id：[" + userId + "],无权限");
        }
        return outDTO.getData();
    }
}
